/*
 * Copyright (c) 2008 Golden T Studios.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.golden.gamedev.object.collision;

/**
 * Optimized <code>java.awt.Rectangle</code> with double precision. The default
 * sprite collision bounding box. <br />
 * <br />
 * This class was made final in 0.2.4, as it is not meant to be extended. GTGE
 * will consistently use the {@link CollisionShape} interface internally, so if
 * a new {@link CollisionShape} instance is required, it can be created without
 * subclassing the {@link CollisionRect} class.
 * 
 * @see CollisionShape
 */
public final class CollisionRect implements CollisionShape {
	
	/**
	 * Serializable ID generated by Eclipse.
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * The <code>x</code>-coordinate of this collision rect.
	 * @deprecated Do not access this value directly, as it will no longer be
	 *             publicly accessible in 0.2.5. Use {@link #setX(double)} to
	 *             set and {@link #getX()} to get this value instead.
	 */
	public double x;
	
	/**
	 * The <code>y</code>-coordinate of this collision rect.
	 * @deprecated Do not access this value directly, as it will no longer be
	 *             publicly accessible in 0.2.5. Use {@link #setY(double)} to
	 *             set and {@link #getY()} to get this value instead.
	 */
	public double y;
	
	/**
	 * The width of this collision rect.
	 * @deprecated Do not access this value directly, as it will no longer be
	 *             publicly accessible in 0.2.5. Use {@link #setWidth(int)} to
	 *             set and {@link #getWidth()} to get this value instead.
	 */
	public int width;
	
	/**
	 * The height of this collision rect.
	 * @deprecated Do not access this value directly, as it will no longer be
	 *             publicly accessible in 0.2.5. Use {@link #setHeight(int)} to
	 *             set and {@link #getHeight()} to get this value instead.
	 */
	public int height;
	
	/**
	 * Creates new <code>CollisionRect</code>.
	 */
	public CollisionRect() {
		super();
	}
	
	/**
	 * Creates and returns a new {@link CollisionRect} instance with a copy of
	 * the position, height and width of the given non-null
	 * {@link CollisionShape} instance.
	 * @param shape The given non-null {@link CollisionShape} instance to copy.
	 * @throws IllegalArgumentException Throws an
	 *         {@link IllegalArgumentException} if the given
	 *         {@link CollisionShape} instance is null.
	 */
	public CollisionRect(final CollisionShape shape) {
		if (shape == null) {
			throw new IllegalArgumentException(
			        "The CollisionShape instance may not be null.");
		}
		this.setBounds(shape.getX(), shape.getY(), shape.getWidth(), shape
		        .getHeight());
	}
	
	/**
	 * Grows this collision rect by <code>h</code> width, and <code>v</code>
	 * height.
	 * @deprecated Because of possible unanticipated side-effects for negative
	 *             values of h and v, this method is deprecated and will be
	 *             removed in 0.2.5. Use
	 *             {@link #setBounds(double, double, int, int)} to grow or
	 *             shrink the {@link CollisionRect} instead.
	 */
	public void grow(int h, int v) {
		if (h >= 0) {
			this.width += h;
		}
		else {
			this.x += h;
			this.width -= h;
		}
		if (v >= 0) {
			this.height += v;
		}
		else {
			this.y += v;
			this.height -= v;
		}
	}
	
	/**
	 * Shrinks this collision rect by <code>h</code> width, and <code>v</code>
	 * height.
	 * @deprecated Because of possible unanticipated side-effects for negative
	 *             values of h and v, this method is deprecated and will be
	 *             removed in 0.2.5. Use
	 *             {@link #setBounds(double, double, int, int)} to grow or
	 *             shrink the {@link CollisionRect} instead.
	 */
	public void shrink(int h, int v) {
		if (h >= 0) {
			this.width -= h;
		}
		else {
			this.x -= h;
			this.width += h;
		}
		if (v >= 0) {
			this.height -= v;
		}
		else {
			this.y -= v;
			this.height += v;
		}
	}
	
	public boolean intersects(CollisionShape shape) {
		return (this.x + this.width > shape.getX()
		        && this.x < shape.getX() + shape.getWidth()
		        && this.y + this.height > shape.getY() && this.y < shape.getY()
		        + shape.getHeight());
	}
	
	public void setBounds(double x1, double y1, int w1, int h1) {
		this.x = x1;
		this.y = y1;
		this.width = w1;
		this.height = h1;
	}
	
	/**
	 * Sets the boundary of this colllision rect to be same with specified
	 * collision shape.
	 * @deprecated This method is deprecated with no direct replacement and will
	 *             be removed in 0.2.5. If this functionality is needed,
	 *             {@link #setBounds(double, double, int, int)} can be invoked -
	 *             however, this is often used where a constructor's cost is
	 *             insignificant - for this use, use
	 *             {@link CollisionRect#CollisionRect(CollisionShape)} to easily
	 *             create a copy of a {@link CollisionShape} instance.
	 */
	public void setBounds(CollisionShape shape) {
		this.setBounds(shape.getX(), shape.getY(), shape.getWidth(), shape
		        .getHeight());
	}
	
	public void setLocation(double x1, double y1) {
		this.x = x1;
		this.y = y1;
	}
	
	public void move(double dx, double dy) {
		this.x += dx;
		this.y += dy;
	}
	
	public double getX() {
		return this.x;
	}
	
	public double getY() {
		return this.y;
	}
	
	public int getWidth() {
		return this.width;
	}
	
	public int getHeight() {
		return this.height;
	}
	
	public final void setX(double x) {
		this.x = x;
	}
	
	public final void setY(double y) {
		this.y = y;
	}
	
	/**
	 * Sets the width of this collision rect.
	 * @param width The width of this collision rect.
	 */
	public final void setWidth(int width) {
		this.width = width;
	}
	
	/**
	 * Sets the height of this collision rect.
	 * @param height The height of this collision rect.
	 */
	public final void setHeight(int height) {
		this.height = height;
	}
	
	public String toString() {
		return super.toString() + " " + "[x=" + this.x + ", y=" + this.y
		        + ", width=" + this.width + ", height=" + this.height + "]";
	}
	
}
